package com.cy.pj.sys.common.config;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.ShiroFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

@Configuration
public class SpringShiroConfig {
    /*
    构建并初始化SecurityManager对象。然后将该对象交给spring管理
    说明@Bean注解应用于，@Configration注解描述类的内部？？？
    通过该注解描述的方法，方法的返回值会交给spring管理，默认bean的名字为
    方法名，
    @return 返回值shiro中的安全管理器对象，是shiro框架的核心，此对象中
    实现了认证，授权，会话，缓存，加密等一系列功能的实现
     */
    //1.在shiro配置类中配置SecurityManager配置，注意要使用
    @Bean      //apache.shiro中的SecurityManager
    public SecurityManager securityManager(Realm realm){
        DefaultWebSecurityManager sManager=new DefaultWebSecurityManager();
        sManager.setRealm(realm);
        return sManager;
    }
    //2.在shiro配置类中添加ShiroFilterFactoryBean对象的配置
    //通过此对象设置匿名访问，认证访问，关键代码如下
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactory(SecurityManager securityManager){
        ShiroFilterFactoryBean sfBean=new ShiroFilterFactoryBean();
        sfBean.setSecurityManager(securityManager);
        //假如没有认证请求先访问此认证的url
        sfBean.setLoginUrl("/doLoginUI");
        LinkedHashMap<String,String> map=new LinkedHashMap<>();
        //静态资源允许匿名访问："anon"
        map.put("/bower_components/**","anon");
        map.put("/build/**","anon");
        map.put("/dist/**","anon");
        map.put("/plugins/**","anon");
        map.put("/user/doLogin","anon");
        //除了匿名访问的资源，其他都要认证"authc"后访问
        map.put("/**","authc");
        sfBean.setFilterChainDefinitionMap(map);
        return sfBean;
    }
    //配置advisor对象，此对象会在spring启动时加载
    //并且通过此对象可以找到@RequiredPermissions注解描述的方法，然后这些方法在运行时，由
    //此Advisor对象，调用SecurityManager中的授权方法checkPermissions方法为访问目标切入点方法的用户
    // 做授权操作
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;//配置advisor对象，shiro框架底层会通过这个对象的matchs方法返回值
        //（类似与切入点）决定是否创建代理对象，进行权限控制
    }

}
